import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutterlogistics/common/constant.dart';

import 'apis.dart';

class DioManager {
  static final tag = 'DioManager';
  static final DioManager _singleton = DioManager._init();
  static Dio _dio;

  DioManager._init() {
    var options = BaseOptions();
    options.receiveTimeout = 1000 * 10;
    options.connectTimeout = 1000 * 10;
    options.baseUrl = TravelApi.baseUrl;
    options.responseType = ResponseType.json;
    _dio = Dio(options);
    _dio.interceptors
        .add(LogInterceptor(responseBody: Constant.isDebug)); //是否开启请求日志
  }

  factory DioManager() {
    return _singleton;
  }

  Map<String, dynamic> parseData(String data) {
    return json.decode(data);
  }

  // 数据返回格式统一，统一处理异常
  Future<Map> request<T>(String method, String url,
      {dynamic data,
      Map<String, dynamic> queryParameters,
      CancelToken cancelToken,
      Options options}) async {
    Response response;
    try {
      response = await _dio.request(url,
          data: data,
          queryParameters: queryParameters,
          options: _checkOptions(method, options, url),
          cancelToken: cancelToken);
      if (response.statusCode == HttpStatus.ok) {
        return new Map<String, dynamic>.from(response.data);
      }
    } on DioError catch (e) {
      formatError(e);
    }
    return new Future.error(new DioError(
      response: response,
      error: "statusCode: $response.statusCode, service error",
      type: DioErrorType.RESPONSE,
    ));
  }

  // 数据字符串类型返回
  Future<String> requestStr<T>(String method, String url,
      {dynamic data,
      Map<String, dynamic> queryParameters,
      CancelToken cancelToken,
      Options options}) async {
    Response response;
    try {
      response = await _dio.request(url,
          data: data,
          queryParameters: queryParameters,
          options: _checkOptions(method, options, url,
              responseType: ResponseType.plain),
          cancelToken: cancelToken);
      if (response.statusCode == HttpStatus.ok) {
        return response.data.toString();
      }
    } on DioError catch (e) {
      formatError(e);
    }
    return new Future.error(new DioError(
      response: response,
      error: "statusCode: $response.statusCode, service error",
      type: DioErrorType.RESPONSE,
    ));
  }

  Options _checkOptions(method, options, url, {responseType}) {
//    String token = UserInfoManager().getUserAccessToken();
    if (options == null) {
      options = new Options();
    }
    options.method = method;
    Map<String, dynamic> _headers = new Map();
//    if (url.toString().contains('auth/oauth/token')) {
//      _headers["Authorization"] = ' Basic YXBwOmFwcA==';
//      _headers["content-type"] = 'application/x-www-form-urlencoded';
//    } else {
//      _headers["Authorization"] = 'Bearer ' + token;
//    }
    if (responseType != null) {
      options.responseType = responseType;
    }
    options.headers = _headers;
    return options;
  }

  /// error统一处理
  void formatError(DioError e) {
    if (e.type == DioErrorType.CONNECT_TIMEOUT) {
      // It occurs when url is opened timeout.
      print("连接超时");
    } else if (e.type == DioErrorType.SEND_TIMEOUT) {
      // It occurs when url is sent timeout.
      print("请求超时");
    } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
      //It occurs when receiving timeout
      print("响应超时");
    } else if (e.type == DioErrorType.RESPONSE) {
      // When the server response, but with a incorrect status, such as 404, 503...
      print("出现异常");
      parseErrorData(e.response.data);
    } else if (e.type == DioErrorType.CANCEL) {
      // When the request is cancelled, dio will throw a error with this type.
      print("请求取消");
    } else {
      //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null.
      print("未知错误");
    }
  }
}

void parseErrorData(data) {}

class Method {
  static final String get = "GET";
  static final String post = "POST";
  static final String put = "PUT";
  static final String head = "HEAD";
  static final String delete = "DELETE";
  static final String patch = "PATCH";
}
